home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume1 / vnews / part3 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  58.0 KB

  1. From: decvax!vax135!hou3c!ka
  2. Date: Mon, 21 Jan 85 22:07:41 est
  3. Newsgroups: mod.sources
  4. Subject: Vnews part 3
  5.  
  6. # Welcome to vnews release 2.11-B 1/17/85.
  7. # This is part 3 out of 7.
  8. # Feed me into sh (NOT csh).
  9.  
  10. if test ! -d lib
  11. then    mkdir lib
  12. fi
  13.  
  14. cat > lib/gethead.c <<\!E!O!F!
  15. #include <stdio.h>
  16. #include <sys/types.h>
  17. #include "config.h"
  18. #include "defs.h"
  19. #include "arthead.h"
  20.  
  21.  
  22. static char *hdname[NHDNAME + 1] = {
  23.       "Relay-Version",
  24.       "Posting-Version",
  25.       "Path",
  26.       "From",
  27.       "Newsgroups",
  28.       "Subject",
  29.       "Message-ID",
  30.       "Date",
  31.       "Article-I.D.",
  32.       "Posted",
  33.       "Date-Received",
  34.       "Expires",
  35.       "References",
  36.       "Control",
  37.       "Sender",
  38.       "Reply-To",
  39.       "Followup-To",
  40.       "Distribution",
  41.       "Organization",
  42.       "Lines",
  43.       "Keywords",
  44.       "Approved",
  45.       "Summary",
  46.       "Priority",
  47.       0
  48. };
  49.  
  50.  
  51.  
  52. FILE *
  53. gethead(hp, fp)
  54.       register struct arthead *hp ;
  55.       FILE *fp ;
  56.       {
  57.       char line[LBUFLEN] ;
  58.       register char *p ;
  59.       register char **pp ;
  60.       register int i ;
  61.       char *spnext ;
  62.       int spleft ;
  63.       int spnum ;
  64.       int unreccnt ;
  65.       extern char FULLSYSNAME[] ;
  66.       char *index(), *ckmalloc() ;
  67.       char *hfgets() ;
  68.  
  69.       for (pp = &hp->h_from, i = NHDNAME + NUNREC ; --i >= 0 ; *pp++ = 0) ;
  70.       unreccnt = 0 ;
  71.       spleft = 0 ;
  72.       spnum = 0 ;
  73.       while (hfgets(line, LBUFLEN, fp) != NULL && line[0] != '\n') {
  74.             if ((p = index(line, ':')) == NULL)
  75.                   goto bad ;
  76.             *p = '\0' ;
  77.             if (index(line, ' ') != NULL)    /* this test unnecessary */
  78.                   goto bad ;
  79.             for (pp = hdname ; *pp ; pp++) {
  80.                   if (**pp == line[0] && strcmp(*pp, line) == 0)
  81.                         break ;
  82.             }
  83.             if (*pp) {
  84.                   while (*++p == ' ') ;
  85.                   if (pp == hdname + 2) {    /* Path: */
  86.                         if (prefix(p, FULLSYSNAME)
  87.                          && index(NETCHRS, p[i = strlen(FULLSYSNAME)]))
  88.                               p += i + 1 ;
  89.                   }
  90.                   pp = &hp->h_relayversion + (pp - hdname) ;
  91.             } else {
  92.                   *p = ':' ;
  93.                   p = line ;
  94.                   if (unreccnt >= NUNREC)
  95.                         continue ;        /* ignore if won't fit */
  96.                   pp = &hp->h_unrec[unreccnt++] ;
  97.             }
  98.             nstrip(p) ;
  99.             i = strlen(p) + 1;
  100.             if (i > spleft) {
  101.                   if (spnum >= 8)
  102.                         xerror("Out of header space") ;
  103.                   if (hp->h_space[spnum] == NULL)
  104.                         hp->h_space[spnum] = ckmalloc(H_SPACE) ;
  105.                   spnext = hp->h_space[spnum++] ;
  106.                   spleft = H_SPACE ;
  107.             }
  108.             *pp = spnext ;
  109.             strcpy(spnext, p) ;
  110.             spnext += i ;
  111.             spleft -= i ;
  112.       }
  113.       if (hp->h_from != NULL && hp->h_path != NULL && hp->h_subdate != NULL && hp->h_ident != NULL)
  114.             return fp ;
  115. bad:
  116.       return NULL ;
  117. }
  118. !E!O!F!
  119.  
  120. cat > lib/getopt.c <<\!E!O!F!
  121. /*
  122.  * getopt - get option letter from argv
  123.  * This version of getopt was written by Henry Spencer
  124.  * and is in the public domain.
  125.  */
  126.  
  127. #include <stdio.h>
  128. #include "config.h"
  129.  
  130. char    *optarg;    /* Global argument pointer. */
  131. int    optind = 0;    /* Global argv index. */
  132.  
  133. static char    *scan = NULL;    /* Private scan pointer. */
  134.  
  135. extern char    *index();
  136.  
  137. int
  138. getopt(argc, argv, optstring)
  139. int argc;
  140. char *argv[];
  141. char *optstring;
  142. {
  143.     register char c;
  144.     register char *place;
  145.  
  146.     optarg = NULL;
  147.  
  148.     if (scan == NULL || *scan == '\0') {
  149.         if (optind == 0)
  150.             optind++;
  151.     
  152.         place = argv[optind];
  153.         if (optind >= argc || place[0] != '-' || place[1] == '\0')
  154.             return(EOF);
  155.         optind++;
  156.         if (strcmp(place, "--")==0) {
  157.             return(EOF);
  158.         }
  159.     
  160.         scan = place + 1;
  161.     }
  162.  
  163.     c = *scan++;
  164.     place = index(optstring, c);
  165.  
  166.     if (place == NULL || c == ':') {
  167.         fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
  168.         return('?');
  169.     }
  170.  
  171.     place++;
  172.     if (*place == ':') {
  173.         if (*scan != '\0') {
  174.             optarg = scan;
  175.             scan = NULL;
  176.         } else {
  177.             if ((optarg = argv[optind]) == NULL) {
  178.                 fprintf(stderr, "%s: no arg for -%c option\n", c);
  179.                 return('?');
  180.             }
  181.             optind++;
  182.         }
  183.     }
  184.  
  185.     return(c);
  186. }
  187. !E!O!F!
  188.  
  189. cat > lib/getuser.c <<\!E!O!F!
  190. /*
  191.  * Get the user's name and home directory.
  192.  */
  193.  
  194. #include "config.h"
  195. #include <stdio.h>
  196.  
  197.  
  198. getuser() {
  199.       extern char *username, *userhome;
  200.       extern char *getenv();
  201.  
  202. #if USGREL > 6
  203.       username = getenv("LOGNAME") ;
  204. #else
  205.       username = getenv("USER") ;
  206. #endif
  207.       if ((userhome = getenv("HOME")) == NULL)
  208.             userhome = getenv("LOGDIR") ;        /* PWB??? */
  209.  
  210.       /* if not in environment, get from /etc/passwd file */
  211.       if (username == NULL || userhome == NULL)
  212.             pgetuser() ;
  213. }
  214. !E!O!F!
  215.  
  216. cat > lib/gfopen.c <<\!E!O!F!
  217. #include <stdio.h>
  218. #include "defs.h"
  219. #include "libextern.h"
  220.  
  221. FILE *ngfp ;
  222. int maxng ;
  223.  
  224.  
  225. gfopen() {
  226.       char buf[FPATHLEN] ;
  227.  
  228.       sprintf(buf, "%s/groupfile", LIB);
  229.       if ((ngfp = fopen(buf, "r")) == NULL
  230.        && (sleep(2), ngfp = fopen(buf, "r")) == NULL)
  231.             xerror("can't open newsgroup file") ;
  232.       if (fgets(buf, sizeof buf, ngfp) == NULL)
  233.             xerror("newsgroup file is empty") ;
  234.       maxng = atoi(buf) ;
  235. }
  236.  
  237.  
  238. gfclose() {
  239.       fclose(ngfp) ;
  240.       ngfp = NULL ;
  241. }
  242. !E!O!F!
  243.  
  244. cat > lib/hash.c <<\!E!O!F!
  245. /*
  246.  * Hashing function.
  247.  * First arg is the string, second is the number of elements in the table.
  248.  * Currently, we use a CRC.
  249.  */
  250.  
  251. int
  252. hash(string, nelem)
  253.       char *string ;
  254.       {
  255.       register unsigned char *p ;
  256.       register int h ;
  257.  
  258.       h = 0 ;
  259.       for (p = string ; *p ; ) {
  260.             h = (long)(((long)h << 8) + *p++) % nelem ;
  261.       }
  262.       return h ;
  263. }
  264. !E!O!F!
  265.  
  266. cat > lib/hfgets.c <<\!E!O!F!
  267. #include <stdio.h>
  268.  
  269. /*
  270.  * hfgets is like fgets, but deals with continuation lines.
  271.  * It also ensures that even if a line that is too long is
  272.  * received, the remainder of the line is thrown away
  273.  * instead of treated like a second line.
  274.  */
  275.  
  276. char *
  277. hfgets(buf, len, fp)
  278.       char *buf;
  279.       int len;
  280.       register FILE *fp;
  281.       {
  282.       register int c;
  283.       register char *cp;
  284.  
  285.       cp = fgets(buf, len, fp);
  286.       if (cp == NULL || *cp == '\n')
  287.             return cp;
  288.  
  289.       c = strlen(cp);
  290.       len -= c;
  291.       cp += c - 1;
  292.       if (*cp != '\n') {
  293.             /* Line too long - part read didn't fit into a newline */
  294.             while ((c = getc(fp)) != '\n' && c != EOF);
  295.       }
  296.       while ((c = getc(fp)) == ' ' || c == '\t') {    /* for each cont line */
  297.             /* Continuation line. */
  298.             while ((c = getc(fp)) == ' ' || c == '\t');    /* skip white space */
  299.             if (--len > 0)
  300.                   *cp++ = ' ';
  301.             do {
  302.                   if (--len > 0)
  303.                         *cp++ = c ;
  304.             } while ((c = getc(fp)) != '\n' && c != EOF) ;
  305.       }
  306.       *cp++ = '\n';
  307.       *cp++ = '\0';
  308.       if (c != EOF)        /* Bug in Apollo UN*X */
  309.             ungetc(c, fp);    /* push back first char of next header */
  310.       return buf;
  311. }
  312. !E!O!F!
  313.  
  314. cat > lib/hfree.c <<\!E!O!F!
  315. /*
  316.  * Free up the storage used by a header.
  317.  */
  318.  
  319. #include <stdio.h>
  320. #include <sys/types.h>
  321. #include "arthead.h"
  322.  
  323.  
  324. hfree(hp)
  325.       struct arthead *hp ;
  326.       {
  327.       register int i ;
  328.       register char **p ;
  329.  
  330.       for (i = 8, p = hp->h_space ; --i >= 0 ; p++) {
  331.             if (*p != NULL) {
  332.                   free(*p) ;
  333.                   *p = NULL ;
  334.             }
  335.       }
  336. }
  337. !E!O!F!
  338.  
  339. cat > lib/hxchg.c <<\!E!O!F!
  340. /*
  341.  * Exchange two headers.
  342.  */
  343.  
  344. #include <stdio.h>
  345. #include <sys/types.h>
  346. #include "arthead.h"
  347.  
  348. hxchg(hp1, hp2)
  349.       struct arthead *hp1, *hp2 ;
  350.       {
  351.       register char *p, *q ;
  352.       register char c ;
  353.       register int i ;
  354.  
  355.       p = (char *)hp1, q = (char *)hp2 ;
  356.       for (i = sizeof(struct arthead) ; --i >= 0 ; )
  357.             c = *p, *p++ = *q, *q++ = c ;
  358. }
  359. !E!O!F!
  360.  
  361. cat > lib/index.c <<\!E!O!F!
  362. /*
  363.  * Return the ptr in sp at which the character c appears;
  364.  * NULL if not found
  365.  *
  366.  * These are the v7 index and rindex routines.  The makefile does not
  367.  * place them it the library because every version of UN*X that is
  368.  * supported by this release of netnews has these routines (possibly
  369.  * named strchr/strrchr).  If you are running V6, use these routines.
  370.  */
  371.  
  372. char *
  373. index(sp, c)
  374. register char *sp, c;
  375. {
  376.     do {
  377.         if (*sp == c)
  378.             return(sp);
  379.     } while (*sp++);
  380.     return(NULL);
  381. }
  382.  
  383. /*
  384.  * Return the ptr in sp at which the character c last
  385.  * appears; NULL if not found
  386.  */
  387.  
  388. char *
  389. rindex(sp, c)
  390. register char *sp, c;
  391. {
  392.     register char *r;
  393.  
  394.     r = NULL;
  395.     do {
  396.         if (*sp == c)
  397.             r = sp;
  398.     } while (*sp++);
  399.     return(r);
  400. }
  401. !E!O!F!
  402.  
  403. cat > lib/isadmin.c <<\!E!O!F!
  404. #include <stdio.h>
  405. #include "defs.h"
  406. #ifndef ROOTID
  407. #include <pwd.h>
  408. #endif
  409.  
  410.  
  411. /*
  412.  * Return 1 if the user is the superuser or the netnews administrator.
  413.  */
  414. isadmin() {
  415.       int uid ;
  416. #ifndef ROOTID
  417.       struct passwd *pw ;
  418. #endif
  419.  
  420.       if ((uid = getuid()) == 0)        /* superuser */
  421.             return 1 ;
  422. #ifdef ROOTID
  423.       return uid == ROOTID ;
  424. #else
  425.       return (pw = getpwnam(ADMIN)) != NULL && pw->pw_uid == uid ;
  426. #endif
  427. }
  428.  
  429.  
  430. /* The following code is better for backward compatability, but
  431.    too complex for my liking:
  432.  
  433.       (*
  434.        * No hardwired administrator ID, so we have to do this the
  435.        * hard way.  First we find the person to be notified.  If
  436.        * that fails, we try the user HOME.
  437.        *)
  438.  
  439. #ifdef NOTIFY
  440.       char notify[64] ;
  441.       char fname[64] ;
  442.       FILE *nfd ;
  443.  
  444.       sprintf(fname, "%s/notify", LIB);
  445.       nfd = fopen(fname, "r");
  446.       if (nfd == NULL)
  447.             strcpy(notify, NOTIFY) ;
  448.       else if (fscanf(nfd, "%s", TELLME) == EOF)
  449.             goto nonotify;
  450.       if ((pw = getpwnam(notify)) == NULL)
  451.             goto nonotify;
  452.       return pw->pw_uid == uid;      
  453. #endif
  454.  
  455. nonotify:
  456. #ifdef HOME
  457.       return (pw = getpwnam(HOME)) != NULL && pw->pw_uid == uid;
  458. #else
  459.       return 0;
  460. #endif
  461. #endif ROOTID
  462. }
  463. */
  464. !E!O!F!
  465.  
  466. cat > lib/isre.c <<\!E!O!F!
  467. /*
  468.  * Check for "Re: " at beginning of string.
  469.  */
  470.  
  471. isre(t)
  472.       register char *t ;
  473.       {
  474.       if (t == 0)        /* delete this later */
  475.             return 0 ;
  476.       if (strncmp(t, "Re:", 3) == 0
  477.        || strncmp(t, "re:", 3) == 0
  478.        || strncmp(t, "RE:", 3) == 0)
  479.             return 1 ;
  480.       return 0 ;
  481. }
  482. !E!O!F!
  483.  
  484. cat > lib/launder.c <<\!E!O!F!
  485. /*
  486.  * nglist is the list of newsgroups in an article we want to follow up.
  487.  * Do any special fascist processing to prevent certain kinds of followups.
  488.  * In this case, there are two things we want to do:
  489.  *    All followups to "net.general" are fed to "net.followup".
  490.  *    However, if "net.general" is mentioned along with "net.news.group",
  491.  *        just remove the net.general.
  492.  */
  493.  
  494. #include "config.h"
  495.  
  496. char *index();
  497.  
  498. launder(nglist)
  499. char    *nglist;
  500. {
  501.     char    *cp;
  502.     char    outbuf[128];
  503.     int    seen_group = 0;
  504.  
  505.     for (cp = index(nglist, 'n'); cp; cp = index(cp + 1, 'n'))
  506.         if (strncmp("news.group", cp, 10) == 0)
  507.             seen_group++;
  508.     for (cp = index(nglist, 'n'); cp; cp = index(cp + 1, 'n'))
  509.         if (strncmp("net.general", cp, 11) == 0) {
  510.             /* 11 = strlen("net.general") */
  511.             strcpy(outbuf, cp + 11);
  512.             if (!seen_group) {
  513.                 strcpy(cp, "net.followup");
  514.                 cp += 12;  /* 12 = strlen("net.followup") */
  515.             }
  516.             if (cp[-1] == ',' && outbuf[0] == ',')
  517.                 cp--;
  518.             strcpy(cp, outbuf);
  519.         }
  520. }
  521. !E!O!F!
  522.  
  523. cat > lib/lcase.c <<\!E!O!F!
  524. #include <ctype.h>
  525.  
  526. #ifdef _tolower
  527. #define tolower(c) _tolower(c)
  528. #endif
  529.  
  530.  
  531. lcase(s)
  532. register char *s;
  533. {
  534.     register char *ptr;
  535.  
  536.     for (ptr = s; *ptr; ptr++)
  537.         if (isupper(*ptr))
  538.             *ptr = tolower(*ptr);
  539. }
  540. !E!O!F!
  541.  
  542. cat > lib/letter <<\!E!O!F!
  543. To: cbosgd!uucp-news
  544. Subject: Vnews status
  545.  
  546. I have done quite a bit to the vnews internals.
  547.  
  548. Vnews now generates the article index for a newsgroup using a file
  549. called artfile instead of openning each article in the newsgroup;
  550. this makes entering a new newsgroup faster.  Currently records
  551. are added to artfile by a program called afinsert which is invoked
  552. from the sys file.  This requires a mod to inews to pass the history
  553. line to afinsert.  There is a program called afbuild which rebuilds
  554. artfile from the history file.  Since afbuild has to open all the
  555. articles in the spool file, it takes about as long to run as the
  556. expire program does, which I hope is acceptable.  Of course, expire
  557. could be rewritten to deal with both artfile and the history file
  558. at some point.
  559.  
  560. I have changed the vnews source around quite a bit.  I have squeezed
  561. it to the point where it should fit on a PDP-11.  One problem I faced
  562. was that the files funcs.c and rfuncs.c contained a number of routines
  563. that were not needed for netnews, so vnews currently does not share
  564. any source code with the rest of netnews.  What I have done, however,
  565. is to take many of the vnews routines and put them in a library called
  566. rlib.a so that they can be used by other netnews programs.  The file
  567. /usr/local/src/cmd/news/lib/routines.doc on cbosgd contains a copy of
  568. the documentation on the routines in rlib.a.  I can mail a copy to
  569. this list if people don't have access to cbosgd.
  570.  
  571. The library comes with a shell program called setup to handle compila-
  572. tion options.  This is hopefully a simpler approach than the localize.sh
  573. stuff that comes with release 2.10.  (For example, if you do not specify
  574. which version of UNIX you are running under, setup figures it out.)
  575. Setup creates files named config.h and newsdefs.h, which specify the
  576. oeprating system and other news parameters, respectively.  It also
  577. creates a file called makedefs, which can be prepended to a makefile or
  578. shell procedure.  Setup currently does not define everything that pro-
  579. grams like inews need, but it could be expanded without too much difficulty.
  580.  
  581. The "ud" (unsibscribe to discussion) command has been installed in vnews
  582. but needs a little work.  The rest of vnews appears to be in pretty good
  583. shape at this point.
  584.  
  585. I am not going to be able to do much on vnews for the next several weeks,
  586. but I would like to try to get a release of netnews out sometime in the
  587. forseeable future.  How are other pieces coming?
  588.                 Kenneth Almquist
  589. !E!O!F!
  590.  
  591. cat > lib/libextern.h <<\!E!O!F!
  592. /*
  593.  * Extern variables defined by library routines.
  594.  */
  595.  
  596. extern char LIB[];        /* /usr/lib/news */
  597. extern char SPOOL[];        /* spool directory */
  598. extern char FULLSYSNAME[];    /* system name */
  599. extern char DOMAIN[];        /* append to FULLSYSNAME to get domain name */
  600. extern char MAILPARSER[];    /* recmail program */
  601. extern char XINEWS[];        /* inews program */
  602. extern char CAESAR[];        /* caesar decryption program */
  603. extern char newsrc[];        /* name of .newsrc file */
  604. extern char *username;        /* user's login name */
  605. extern char *userhome;        /* user's login directory */
  606. extern char bfr[];        /* general purpose buffer */
  607. !E!O!F!
  608.  
  609. cat > lib/logdir.c <<\!E!O!F!
  610. /*
  611.  *    UNIX shell - logdir routine
  612.  *
  613.  *    Joe Steffen
  614.  *    Bell Telephone Laboratories
  615.  *
  616.  *    This routine does not use the getpwent(3) library routine
  617.  *    because the latter uses the stdio package.  The allocation of
  618.  *    storage in this package destroys the integrity of the shell's
  619.  *    storage allocation.
  620.  *
  621.  *    Modified 2/82 by DJ Molny
  622.  *
  623.  *    This routine now implements name cacheing, so multiple requests
  624.  *    for the same logdir do not result in multiple open/reads of
  625.  *    /etc/passwd.  If the previous request was successful and the name
  626.  *    is the same as the last request, the same login directory is returned.
  627.  */
  628.  
  629. #define    BUFSIZ    160
  630.  
  631. static char line[BUFSIZ+1];
  632.  
  633. char *
  634. logdir(name)
  635. char *name;
  636. {
  637.     int    pwf;
  638.     static char lastname[BUFSIZ+1];
  639.     static char lastdir[BUFSIZ+1];
  640.     register char *p;
  641.     register int i, j;
  642.     char *field();
  643.     
  644.     if (*lastdir && !strcmp(lastname,name))        /* djm */
  645.         return(lastdir);
  646.  
  647.     strcpy(lastname,name);            /* djm */
  648.     strcpy(lastdir,"");            /* djm */
  649.  
  650.     /* attempt to open the password file */
  651.     if ((pwf = open("/etc/passwd", 0)) == -1)
  652.         return(0);
  653.         
  654.     /* find the matching password entry */
  655.     do {
  656.         /* get the next line in the password file */
  657.         i = read(pwf, line, BUFSIZ);
  658.         for (j = 0; j < i; j++)
  659.             if (line[j] == '\n')
  660.                 break;
  661.         /* return a null pointer if the whole file has been read */
  662.         if (j >= i)
  663.             return(0);
  664.         line[++j] = 0;            /* terminate the line */
  665.         lseek(pwf, (long) (j - i), 1);    /* point at the next line */
  666.         p = field(line);        /* get the logname */
  667.     } while (strcmp(name, line) != 0);
  668.     close(pwf);
  669.     
  670.     /* skip the intervening fields */
  671.     p = field(p);
  672.     p = field(p);
  673.     p = field(p);
  674.     p = field(p);
  675.     
  676.     /* return the login directory */
  677.     field(p);
  678.     strcpy(lastdir,p);            /* djm */
  679.     return(p);
  680. }
  681.  
  682. static char *
  683. field(p)
  684. register char *p;
  685. {
  686.     while (*p && *p != ':')
  687.         ++p;
  688.     if (*p) *p++ = 0;
  689.     return(p);
  690. }
  691. !E!O!F!
  692.  
  693. cat > lib/lookup.c <<\!E!O!F!
  694. #include <stdio.h>
  695. #include "af.h"
  696.  
  697.  
  698. /*
  699.  * Look up an article using the article id.
  700.  */
  701.  
  702. DPTR
  703. lookart(id, a)
  704.       char *id ;
  705.       struct artrec *a ;
  706.       {
  707.       DPTR dp ;
  708.  
  709.       dp = readptr(hashid(id)) ;
  710.       while (dp != DNULL) {
  711.             readrec(dp, a) ;
  712.             if (equal(id, a->a_ident)) {
  713.                   /*printf("lookart %s succeeded\n", id) ;    /*DEBUG*/
  714.                   return dp ;
  715.             }
  716.             dp = a->a_idchain ;
  717.       }
  718.       /*printf("lookart %s failed\n", id) ;            /*DEBUG*/
  719.       return DNULL ;
  720. }
  721. !E!O!F!
  722.  
  723. cat > lib/makehimask.c <<\!E!O!F!
  724. /*
  725.  * Unless the newsgroup is asked for explicitly, delete it from the
  726.  * subscription list.
  727.  */
  728.  
  729. #include <stdio.h>
  730. #include "config.h"
  731. #include "str.h"
  732.  
  733. makehimask(sublist, ngrp)
  734.       register char *sublist ;
  735.       char *ngrp ;
  736.       {
  737.       char c, *p ;
  738.       char *index() ;
  739.  
  740.       for (;;) {
  741.             if (prefix(sublist, ngrp)
  742.              && (c = sublist[strlen(ngrp)]) == '\0' || c == ',')
  743.                   return ;
  744.             if ((p = index(sublist, ',')) == NULL)
  745.                   break ;
  746.             sublist = p + 1 ;
  747.       }
  748.       while (*sublist)
  749.             sublist++ ;
  750.       if (sublist[-1] != ',')
  751.             *sublist++ = ',' ;
  752.       *sublist++ = '!' ;
  753.       scopy(ngrp, sublist) ;
  754. }
  755. !E!O!F!
  756.  
  757. cat > lib/mkconfig <<\!E!O!F!
  758. #!/bin/sh
  759. if test "$1" = ""
  760. then    echo "Usage: mkconfig dir"
  761.     echo "where dir is the directory containing the 2.10.1 source"
  762.     exit 1
  763. fi
  764.  
  765. if test ! -d $1
  766. then    echo "mkconfig: $1: no such directory"
  767.     exit 1
  768. fi
  769.  
  770. (
  771. sed -n    -e 's/^NEWSUSR *= */newsusr /p' \
  772.     -e 's/^NEWSGRP *= */newsgrp /p' \
  773.     -e 's/^LIBDIR *= */lib /p' \
  774.     -e 's/^BINDIR *= */bin /p' \
  775.     -e 's/^SPOOLDIR *= */spool /p' \
  776.         $1/Makefile
  777. sed -n    -e 's/^#define[     ]NOTIFY[     ]*"\([^"]*\)".*/notify \1/p' \
  778.     -e 's/^#define[     ]MYDOMAIN[     ]*"\([^"]*\)".*/mydomain \1/p' \
  779.     -e 's/^#define[     ]MYORG[     ]*"\([^"]*\)".*/myorg \1/p' \
  780.     -e 's/^#define[     ]DFLTSUB[     ]*"\([^"]*\)".*/dfltsub \1/p' \
  781.     -e 's/^#define[     ]ADMSUB[     ]*"\([^"]*\)".*/admsub \1/p' \
  782.     -e 's/^#define[     ]UNAME.*/uname/p' \
  783.     -e 's/^#define[     ]GHNAME.*/ghname/p' \
  784.     -e 's/^\/\*[     ]*#define[     ]INTERNET.*/internet no/p' \
  785.     -e 's/^\/\*[     ]*#define[     ]V7MAIL.*/v7mail no/p' \
  786.     -e 's/^#define[     ]X[     ]*"\([^"]*\)".*/x \1/p' \
  787.         $1/defs.h
  788. rootid=`sed -n -e 's/^#define[     ]ROOTID[     ]*\([0-9]*\).*/\1/p' $1/defs.h`
  789. rootname=`sed -n -e "/^[^:]*:[^:]*:$rootid:/s/:.*//p" /etc/passwd | sed '2,$d'`
  790. if test "$rootname" != ""
  791. then    echo admin $rootname
  792. fi
  793. ) | sed    -e '/lib \/usr\/lib\/news/d' \
  794.     -e '/bin \/usr\/bin/d' \
  795.     -e '/spool \/usr\/spool\/news/d' \
  796.     -e '/dfltsub all/d' \
  797.     -e '/admsub general,all\.announce/d' \
  798.         > config
  799. !E!O!F!
  800. chmod +x lib/mkconfig
  801.  
  802. cat > lib/mypathinit.c <<\!E!O!F!
  803. #include <stdio.h>
  804. #include "config.h"
  805. #include "defs.h"
  806.  
  807.  
  808. #ifdef HOME
  809. char SPOOL[FPATHLEN];
  810. char LIB[FPATHLEN-15];
  811. char CAESAR[FPATHLEN];
  812. #else
  813. char SPOOL[] = SPOOLDIR";
  814. char LIB[] = LIBDIR";
  815. char CAESAR[] = LIBDIR/caesar";
  816. #endif HOME
  817. #ifdef MYNAME
  818. char FULLSYSNAME[] = MYNAME;
  819. #else
  820. #ifdef UNAME
  821. #include <sys/utsname.h>
  822. char FULLSYSNAME[9];
  823. #else
  824. char FULLSYSNAME[20];
  825. #endif UNAME
  826. #endif MYNAME
  827. char DOMAIN[] = MYDOMAIN;
  828. #ifdef SENDMAIL
  829. char MAILPARSER[] = SENDMAIL;
  830. #else
  831. #ifdef HOME
  832. char MAILPARSER[FPATHLEN];
  833. #else
  834. char MAILPARSER[] = LIBDIR/recmail";
  835. #endif HOME
  836. #endif SENDMAIL
  837. char XINEWS[] = INEWS;
  838. static char verpfx[4] = {'@', '(', '#', ')'};
  839. char NEWS_VERSION[] = news_version;
  840.  
  841.  
  842. pathinit() {
  843. #ifdef HOME
  844.       /* Relative to the home directory of user HOME */
  845.       sprintf(SPOOL, "%s/%s", logdir(HOME), SPOOLDIR");
  846.       sprintf(LIB, "%s/%s", logdir(HOME), LIBDIR");
  847. #endif
  848.       if (strlen(LIB) >= FPATHLEN-15)
  849.             xerror("LIB too long");
  850.       if (strlen(SPOOL) > FPATHLEN)
  851.             xerror("SPOOL too long");
  852. #if defined(HOME) && !defined(SENDMAIL)
  853.       sprintf(MAILPARSER, "%s/recmail", LIB);
  854. #endif
  855. #ifndef MYNAME
  856. #ifdef UNAME
  857.       {
  858.             struct utsname ubuf;
  859.             uname(&ubuf);
  860.             strcpy(FULLSYSNAME, ubuf.nodename);
  861.       }
  862. #else
  863. #ifdef GHNAME
  864.       gethostname(FULLSYSNAME, sizeof FULLSYSNAME);
  865. #else
  866.       whoami();
  867. #endif GHNAME
  868. #endif UNAME
  869. #endif MYNAME
  870. }
  871.  
  872.  
  873. #if !defined(UNAME) && !defined(GHNAME) && !defined(MYNAME)
  874. #define    HDRFILE "/usr/include/whoami.h"
  875.  
  876. whoami()
  877. {
  878.     char buf[BUFSIZ];
  879.     FILE *fd;
  880.     
  881.     fd = fopen(HDRFILE, "r");
  882.     if (fd == NULL) {
  883.         fprintf(stderr, "Cannot open %s\n", HDRFILE);
  884.         exit(1);
  885.     }
  886.     
  887.     for (;;) {    /* each line in the file */
  888.         if (fgets(buf, sizeof buf, fd) == NULL) {
  889.             fprintf(stderr, "no sysname in %s\n", HDRFILE);
  890.             fclose(fd);
  891.             exit(2);
  892.         }
  893.         if (sscanf(buf, "#define sysname \"%[^\"]\"", FULLSYSNAME) == 1) {
  894.             fclose(fd);
  895.             return;
  896.         }
  897.     }
  898. }
  899. #endif
  900. !E!O!F!
  901.  
  902. cat > lib/ndir.h <<\!E!O!F!
  903. #if BSDREL >= 42
  904. #include <sys/dir.h>
  905. #else
  906.  
  907. #if defined(pdp11) || USGREL == 30
  908. #define DIRBLKSIZ 512
  909. #else
  910. #define DIRBLKSIZ 1024
  911. #endif
  912.  
  913. struct    direct {
  914.     long    d_ino;            /* inode number of entry */
  915.     short    d_namlen;        /* length of string in d_name */
  916.     char    d_name[16];        /* name must be no longer than this */
  917. };
  918.  
  919. /*
  920.  * Definitions for library routines operating on directories.
  921.  */
  922. typedef struct {
  923.     int    dd_fd;
  924.     int    dd_nleft;
  925.     char    *dd_nextc;
  926.     char    dd_buf[DIRBLKSIZ];
  927. } DIR;
  928.  
  929. #ifndef NULL
  930. #define NULL 0
  931. #endif
  932. extern    DIR *opendir();
  933. extern    struct direct *readdir();
  934. extern    void closedir();
  935. #endif
  936. !E!O!F!
  937.  
  938. cat > lib/newer.c <<\!E!O!F!
  939. /*
  940.  * Program to determine whether file2 needs to be updated from file1.
  941.  * that another one.  Usage:  newer file1 file2
  942.  * Returns:
  943.  *    1  file2 is newer than file1.
  944.  *    0  file2 is older than file1 or one of the files does not exist.
  945.  *    8  arg count.
  946.  */
  947.  
  948. #include <stdio.h>
  949. #include <sys/types.h>
  950. #include <sys/stat.h>
  951.  
  952.  
  953. main(argc, argv)
  954.       char **argv ;
  955.       {
  956.       struct stat st1, st2;
  957.  
  958.       if (argc != 3) {
  959.             fputs("Usage: newer file1 file2\n", stderr);
  960.             exit(8);
  961.       }
  962.       if (stat(argv[1], &st1) < 0) {
  963.             fputs("newer: can't stat ", stderr);
  964.             fputs(argv[1], stderr);
  965.             fputs("\n", stderr);
  966.             exit(0);            /* force update attempt */
  967.       }
  968.       if (stat(argv[2], &st2) < 0 || st2.st_mtime < st1.st_mtime)
  969.             exit(0);
  970.       exit(1);                /* up to date */
  971. }
  972. !E!O!F!
  973.  
  974. cat > lib/newsrc.doc <<\!E!O!F!
  975. 1.  FORMAT OF .NEWSRC FILE
  976.  
  977. Since the .newsrc file is shared between a number of news reading
  978. programs, care should be taken to allow for the evolution of this file.
  979. Lines in the file fall into several types.
  980.  
  981. 1) Newsgroups lines.
  982.  
  983. A newsgroup line consists of a newsgroup name, followed by subscription
  984. indication, followed by a flags field, followed by a list of article
  985. numbers.  A line should not be considered to be a newsgroup line unless
  986. the first character of the line is a lowercase letter and the
  987. subscription indication immediately follows the newsgroup name.
  988.  
  989. The subscription indication consists of a ':' to indicate that the user
  990. subscribes to this group, or an '!' to indicate that the user does not
  991. subscribe to this group.
  992.  
  993. The flags field is currently unused but is reserved for future use.  It
  994. consists of a word not beginning with a digit, and terminated by a
  995. space.
  996.  
  997. The list of article numbers should not have any spaces in it.  It
  998. consists of a comma separated list of articles which have been read.  A
  999. range of articles may be indicated by two numbers separated by a minus
  1000. sign.
  1001.  
  1002. Ideally, newsgroups should be presented in the order in which they
  1003. appear in the .newsrc file, and newsgroups not appearing in the .newsrc
  1004. file should be shown last.  At any rate, the order of newsgroups in
  1005. the .newrc file should not be disturbed.
  1006.  
  1007. The crash recovery code writes updated lines to the end of the .newsrc
  1008. file as they are modified.  Therefore, the last entry in the .newsrc
  1009. file should be believed.  However, the first occurence of a newsgroup
  1010. in the .newsrc file gives it's display position.
  1011.  
  1012. 2)  Unsubscribed discussions.
  1013.  
  1014. Any line beginning with a '<' contains a message-ID of a discussion
  1015. which has been unsubscribed to.  Followups to such articles should not
  1016. be shown.
  1017.  
  1018. 3)  Comment lines.
  1019.  
  1020. All other lines should be treated as comment lines.  When the .newsrc
  1021. file is rewritten, comment lines should be output first.  2.10 deletes
  1022. certain comment lines; this is unacceptable.
  1023. !E!O!F!
  1024.  
  1025. cat > lib/newsrc.h <<\!E!O!F!
  1026. #define MAXUNSUB 200    /* max number discussion unsubscribed from */
  1027. #define MAXRCJUNK 128    /* maximum number of comment lines */
  1028.  
  1029. #define NG_UNSUB 01
  1030.  
  1031. struct ngentry {        /* newsgroup entry */
  1032.     char *ng_name;        /* name of newsgroup */
  1033.     char *ng_bits;        /* which articles have been read */
  1034.     struct ngentry *ng_next;/* next newgroup in .newsrc order */
  1035.     char ng_unsub;        /* set if we have unsubscribed */
  1036. };
  1037.  
  1038. #define ng_num(ngp)    ((ngp) - ngtable)
  1039. #define numtong(num)    (&ngtable[num])
  1040. #ifdef DEBUG
  1041. #define isunread(i)    (i > 0 && i <= maxartno ? _isunread(i) : abort())
  1042. #define clrunread(i)    (i > 0 && i <= maxartno ? _clrunread(i) : abort())
  1043. #define setunread(i)    (i > 0 && i <= maxartno ? _setunread(i) : abort())
  1044. #define _isunread(i)    (bitmap[(i-1) >> 3] & (1 << (i-1) % 8))
  1045. #define _setunread(i)    (bitmap[(i-1) >> 3] |= (1 << (i-1) % 8))
  1046. #define _clrunread(i)    (bitmap[(i-1) >> 3] &= ~(1 << (i-1) % 8))
  1047. #else
  1048. #define isunread(i)    (bitmap[(i-1) >> 3] & (1 << (i-1) % 8))
  1049. #define setunread(i)    (bitmap[(i-1) >> 3] |= (1 << (i-1) % 8))
  1050. #define clrunread(i)    (bitmap[(i-1) >> 3] &= ~(1 << (i-1) % 8))
  1051. #endif
  1052.  
  1053.  
  1054. struct ngentry *findgroup();
  1055. struct ngentry *prevgrp(), *nextgrp();
  1056.  
  1057.  
  1058. extern struct ngentry ngtable[MAXGROUPS];
  1059. extern struct ngentry *curng, *firstng, *lastng;
  1060. extern int ndunsub;
  1061. extern long dunsub[MAXUNSUB];
  1062. extern char *rcjunk[MAXRCJUNK];
  1063. extern char **nextrcjunk;
  1064. extern int minartno;
  1065. extern int maxartno;
  1066. extern char *bitmap;
  1067. !E!O!F!
  1068.  
  1069. cat > lib/nextgrp.c <<\!E!O!F!
  1070. #include <stdio.h>
  1071. #include "defs.h"
  1072. #include "newsrc.h"
  1073.  
  1074.  
  1075. struct ngentry *
  1076. nextgrp(ngp)
  1077.     struct ngentry *ngp;
  1078.     {
  1079.     if (ngp == NULL)
  1080.         return firstng;
  1081.     else
  1082.         return ngp->ng_next;
  1083. }
  1084. !E!O!F!
  1085.  
  1086. cat > lib/ng.h <<\!E!O!F!
  1087. #define MAXNGNAME 32
  1088.  
  1089. #define G_MOD 01        /* indicates moderated or fa.all group */
  1090.  
  1091. struct ngrec {
  1092.       char  g_name[MAXNGNAME];    /* newsgroup name */
  1093.       short g_num;        /* newsgroup number */
  1094.       short g_flags;        /* various flags */
  1095. } ;
  1096.  
  1097. extern int maxng;        /* max value for g_num */
  1098. extern FILE *ngfp;
  1099.  
  1100. #define ALL_GROUPS(ngrec)    for (nginit() ; ngread(&(ngrec)) ; )
  1101. !E!O!F!
  1102.  
  1103. cat > lib/ngchain.c <<\!E!O!F!
  1104. /*
  1105.  * Routines step through all the elements of a newsgroup.
  1106.  * Called by the BNG macro.
  1107.  */
  1108.  
  1109. #include <stdio.h>
  1110. #include "af.h"
  1111.  
  1112.  
  1113. DPTR nglnext ;
  1114.  
  1115.  
  1116. DPTR
  1117. nglfirst(ngnum) {
  1118.       return nglnext = readptr(ngchain(ngnum)) ;
  1119. }
  1120.  
  1121.  
  1122. ARTNO
  1123. ngltest(ngnum, a)
  1124.       int ngnum ;
  1125.       struct artrec *a ;
  1126.       {
  1127.       register int i ;
  1128.  
  1129.       if (nglnext == DNULL)
  1130.             return -1 ;
  1131.       readrec(nglnext, a) ;
  1132.       for (i = 0 ; i < a->a_ngroups ; i++) {
  1133.             if (a->a_group[i].a_ngnum == ngnum) {
  1134.                   nglnext = a->a_group[i].a_ngchain ;
  1135.                   return a->a_group[i].a_artno ;
  1136.             }
  1137.       }
  1138.       xerror("bad newsgroup chain") ;
  1139. }
  1140. !E!O!F!
  1141.  
  1142. cat > lib/ngmatch.c <<\!E!O!F!
  1143. #include "defs.h"
  1144.  
  1145. /*
  1146.  * News group matching.
  1147.  *
  1148.  * nglist is a list of newsgroups.
  1149.  * sublist is a list of subscriptions.
  1150.  * sublist may have "meta newsgroups" in it.
  1151.  * All fields are NGDELIM separated,
  1152.  *
  1153.  * Currently implemented glitches:
  1154.  * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
  1155.  * If subscription X matches Y, it also matches Y.anything.
  1156.  */
  1157. ngmatch(nglist, sublist)
  1158. register char *nglist, *sublist;
  1159. {
  1160.     register char *n, *s;
  1161.     register int rc;
  1162.  
  1163.     rc = 0;
  1164.     for (n = nglist; *n != '\0' && rc == 0;) {
  1165.         for (s = sublist; *s != '\0';) {
  1166.             if (*s != NEGCHAR)
  1167.                 rc |= ptrncmp(s, n);
  1168.             else
  1169.                 rc &= ~ptrncmp(s+1, n);
  1170.             while (*s && *s++ != NGDELIM);
  1171.         }
  1172.         while (*n && *n++ != NGDELIM);
  1173.     }
  1174.     return(rc);
  1175. }
  1176.  
  1177. /*
  1178.  * Compare two newsgroups for equality.
  1179.  * The first one may be a "meta" newsgroup.
  1180.  */
  1181. ptrncmp(ng1, ng2)
  1182. register char *ng1, *ng2;
  1183. {
  1184.     while (*ng1 && *ng1 != NGDELIM) {
  1185.         if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
  1186.             ng1 += 3;
  1187.             while (*ng2 && *ng2 != NGDELIM && *ng2 != '.')
  1188.                 if (ptrncmp(ng1, ng2++))
  1189.                     return(1);
  1190.             return (ptrncmp(ng1, ng2));
  1191.         } else if (*ng1++ != *ng2++)
  1192.             return(0);
  1193.     }
  1194.     return (*ng2 == '\0' || *ng2 == '.' || *ng2 == NGDELIM);
  1195. }
  1196. !E!O!F!
  1197.  
  1198. cat > lib/nsavestr.c <<\!E!O!F!
  1199. /*
  1200.  * Make a copy of a string.  The copy cannot be freed.
  1201.  */
  1202.  
  1203. #include "str.h"
  1204.  
  1205. #define BLOCKSIZE 1024
  1206.  
  1207. static char *savearea;
  1208. static char *savep;
  1209.  
  1210. char *
  1211. nsavestr(s)
  1212.       char *s ;
  1213.       {
  1214.       int size = strlen(s) + 1;
  1215.       char *p ;
  1216.       char *ckmalloc() ;
  1217.  
  1218.       if (size > BLOCKSIZE)
  1219.             return savestr(s) ;
  1220.       if (savearea == 0 || savearea + BLOCKSIZE - savep < size) {
  1221.             nsaveclean() ;
  1222.             savearea = savep = ckmalloc(BLOCKSIZE) ;
  1223.       }
  1224.       scopy(s, p = savep) ;
  1225.       savep += size ;
  1226.       return p ;
  1227. }
  1228.  
  1229.  
  1230. /*
  1231.  * Release unused storage.
  1232.  */
  1233.  
  1234. nsaveclean() {
  1235.       char *realloc() ;
  1236.       if (savearea) {
  1237.             if (realloc(savearea, savep - savearea) != savearea)
  1238.                   xerror("realloc blew it") ;
  1239.       }
  1240.       savearea = 0 ;
  1241. }
  1242. !E!O!F!
  1243.  
  1244. cat > lib/nstrip.c <<\!E!O!F!
  1245. /*
  1246.  * Strip trailing newlines, blanks, and tabs from 's'.
  1247.  * Return 1 if newline was found, else 0.
  1248.  */
  1249. nstrip(s)
  1250. register char *s;
  1251. {
  1252.     register char *p;
  1253.     register int rc;
  1254.  
  1255.     rc = 0;
  1256.     p = s;
  1257.     while (*p)
  1258.         if (*p++ == '\n')
  1259.             rc = 1;
  1260.     while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
  1261.     *++p = '\0';
  1262.     return(rc);
  1263. }
  1264. !E!O!F!
  1265.  
  1266. cat > lib/openrc.c <<\!E!O!F!
  1267. /*
  1268.  * Open the .newsrc file, creating it if necessary.
  1269.  */
  1270.  
  1271. #include <stdio.h>
  1272. #include "defs.h"
  1273. #include "libextern.h"
  1274.  
  1275. char newsrc[64] ;
  1276.  
  1277. FILE *
  1278. openrc() {
  1279.     register char *myrc ;
  1280.     register FILE *rcfp ;
  1281.     static char READ[] = "r" ;
  1282.     char *getenv() ;
  1283.  
  1284.     if ((myrc = getenv("NEWSRC")) != NULL)
  1285.         strcpy(newsrc, myrc);
  1286.     else
  1287.         sprintf(newsrc, "%s/%s", userhome, NEWSRC);
  1288.     if ((rcfp = fopen(newsrc, READ)) == NULL) {
  1289.         newrc() ;
  1290.         if ((rcfp = fopen(newsrc, READ)) == NULL)
  1291.             xerror("Can't create .newsrc file") ;
  1292.     }
  1293.     return rcfp ;
  1294. }
  1295.  
  1296.  
  1297. newrc()
  1298. {
  1299.     register FILE *fp;
  1300.     char users[FPATHLEN];
  1301.  
  1302.     if (close(creat(newsrc, 0666))) {
  1303.         xerror("Cannot create %s", newsrc);
  1304.     }
  1305.  
  1306.     sprintf(users, "%s/users", LIB);
  1307.     if ((fp = fopen(users, "a")) != NULL) {
  1308.         fprintf(fp, "%s\n", username);
  1309.         fclose(fp);
  1310.         chmod(users, 0666);
  1311.     }
  1312. }
  1313. !E!O!F!
  1314.  
  1315. cat > lib/pgetuser.c <<\!E!O!F!
  1316. /*
  1317.  * Get user name and home directory.  This version always goes to the
  1318.  * password file, so it cannot be subverted by modifying the environment.
  1319.  */
  1320.  
  1321. #include <stdio.h>
  1322. #include <pwd.h>
  1323.  
  1324. char *username, *userhome;
  1325.  
  1326. pgetuser()
  1327. {
  1328.     register struct passwd *p;
  1329.     char *savestr();
  1330.     struct passwd *getpwuid();
  1331.  
  1332.     if ((p = getpwuid(getuid())) == NULL)
  1333.         xerror("Cannot get user's name");
  1334.     username = savestr(p->pw_name);
  1335.     userhome = savestr(p->pw_dir);
  1336. }
  1337. !E!O!F!
  1338.  
  1339. cat > lib/prefix.c <<\!E!O!F!
  1340. int
  1341. prefix(full, pref)
  1342.       register char *full, *pref ;
  1343.       {
  1344.       register char c ;
  1345.  
  1346.       while ((c = *pref++) != '\0')
  1347.             if (*full++ != c)
  1348.                   return 0 ;
  1349.       return 1 ;
  1350. }
  1351. !E!O!F!
  1352.  
  1353. cat > lib/prevgrp.c <<\!E!O!F!
  1354. #include <stdio.h>
  1355. #include "defs.h"
  1356. #include "newsrc.h"
  1357.  
  1358.  
  1359. struct ngentry *
  1360. prevgrp(ngp)
  1361.     struct ngentry *ngp;
  1362.     {
  1363.     register struct ngentry *p;
  1364.  
  1365.     if (ngp == NULL)
  1366.         return NULL;
  1367.     for (p = ngtable ; p->ng_next != ngp ; p++)
  1368.         if (p >= ngtable + MAXGROUPS - 1)
  1369.             return NULL;
  1370.     return p;
  1371. }
  1372. !E!O!F!
  1373.  
  1374. cat > lib/process.c <<\!E!O!F!
  1375. /*
  1376.  * process - process options for readnews
  1377.  */
  1378.  
  1379. static char *SccsId = "%W%    %G%";
  1380.  
  1381. #include <stdio.h>
  1382. #include <ctype.h>
  1383. #include "roptions.h"
  1384. #define TRUE 1
  1385. #define FALSE 0
  1386.  
  1387. int mode = UNKNOWN;
  1388.  
  1389.  
  1390. procopt(argv)
  1391. register char **argv;
  1392. {
  1393.       register int state = OPTION;
  1394.       register char *p;
  1395.       register struct optable *optpt;
  1396.       extern char *progname;
  1397.       char *savestr(), *realloc();
  1398.  
  1399.       /* loop once per arg. */
  1400.  
  1401.       while (*argv != NULL) {
  1402.           if (state == OPTION) {
  1403.                   if (**argv != '-') {
  1404.                         xerror("Bad option string \"%s\"", *argv);
  1405.                   }
  1406.                   while (*++*argv != '\0') {
  1407.                         for (optpt = options; optpt->optlet != '\0'; ++optpt) {
  1408.                               if (optpt->optlet == **argv)
  1409.                                     goto found;
  1410.                         }
  1411.                         /* unknown option letter */
  1412.                         fprintf(stderr, "Usage: %s [ -a [ date ]] [ -n newsgroups ] [ -t titles ] [ -lprxhfuM ]\n", progname);
  1413.                         fprintf(stderr, "\t[ -c [ ``mailer'' ]]\n\n");
  1414.                         fprintf(stderr, "       %s -s\n", progname);
  1415.                         exit(1);
  1416.  
  1417.                       found:;
  1418.                         if (mode != UNKNOWN && (mode&optpt->oldmode) == 0) {
  1419.                               xerror("Bad %c option", **argv);
  1420.                         }
  1421.                         if (mode == UNKNOWN)
  1422.                               mode = optpt->newmode;
  1423.                         optpt->flag = TRUE;
  1424.                         state = optpt->newstate;
  1425.                   }
  1426.  
  1427.                   argv++;            /* done with this option arg. */
  1428.  
  1429.           } else {
  1430.  
  1431.                   /*
  1432.                    * Pick up a piece of a string and put it into
  1433.                    * the appropriate buffer.
  1434.                    */
  1435.                   if (**argv == '-') {
  1436.                         state = OPTION;
  1437.                         continue;
  1438.                   }
  1439.  
  1440.                   p = optpt->buf;
  1441.                   if (state == STRING) {
  1442.                         if (optpt->buf != NULL)
  1443.                               free(optpt->buf);
  1444.                         optpt->buf = savestr(*argv);
  1445.                         state++;
  1446.                   } else {
  1447.                         if ((p = realloc(p, strlen(p) + strlen(*argv) + 2)) == NULL)
  1448.                               xerror("No space");
  1449.                         optpt->buf = p;
  1450.                         while (*p)  p++;
  1451.                         *p++ = optpt->filchar;
  1452.                         strcpy(p, *argv);
  1453.                   }
  1454.                   argv++;
  1455.             }
  1456.       }
  1457.  
  1458.       /*
  1459.        * At this point, we are done with vanilla flag processing.
  1460.        * Now deal with defaults and upward compatibility stuff.
  1461.        */
  1462.       return;
  1463. }
  1464.  
  1465.  
  1466. /*
  1467.  * Process a string containing options.  The string is broken up into
  1468.  * space separated options and then passed to procopt.
  1469.  */
  1470.  
  1471. #define MAXOPTS 63
  1472.  
  1473. procostr(rcbuf)
  1474.       char *rcbuf;
  1475.       {
  1476.       register char *ptr;
  1477.       char *rcline[MAXOPTS + 1];
  1478.       int line = -1;
  1479.  
  1480.       strcat(rcbuf, " \1");
  1481.       ptr = rcbuf;
  1482.       while (*++ptr)
  1483.             if (isspace(*ptr))
  1484.                   *ptr = '\0';
  1485.       for (ptr = rcbuf; ; ptr++) {
  1486.             if (!*ptr)
  1487.                   continue;
  1488.             if (*ptr == '\1')
  1489.                   break;
  1490.             if (++line >= MAXOPTS)
  1491.                   xerror("Too many options");
  1492.             rcline[line] = ptr;
  1493.             while (*ptr)
  1494.                   ptr++;
  1495.       }
  1496.       rcline[++line] = NULL;
  1497.       procopt(rcline);
  1498. }
  1499. !E!O!F!
  1500.  
  1501. cat > lib/read.c <<\!E!O!F!
  1502. #include <stdio.h>
  1503. #include "af.h"
  1504. #include "libextern.h"        /* defines bfr */
  1505.  
  1506. long lseek() ;
  1507.  
  1508.  
  1509. /*
  1510.  * Read in an article record.
  1511.  */
  1512.  
  1513. readrec(dp, a)
  1514.       DPTR dp ;
  1515.       struct artrec *a ;
  1516.       {
  1517.       register int len ;
  1518.       int i ;
  1519.       register char *p ;
  1520.       register char *q ;
  1521.       char **pp ;
  1522.  
  1523.       /*printf("readrec %ld\n", (long)dp) ;        /*DEBUG*/
  1524.       if (lseek(affd, (long)dp, 0) < 0)
  1525.             xerror("seek %ld failed, readrec\n", dp) ;
  1526.       len = BSIZE - ((int)dp & (BSIZE - 1)) ;
  1527.       if (len <= 1 + A_WRTLEN + MAXNG * sizeof(struct artgroup))
  1528. #if BSIZE == 512
  1529.             len += BSIZE ;
  1530. #else
  1531.             len = 1 + sizeof(struct artrec) ;
  1532. #endif
  1533.       if ((len = read(affd, bfr, len)) < 1 + A_WRTLEN + MAXNG * sizeof(struct artgroup)) {
  1534.             printf("read returned %d\n", len) ;
  1535.             xerror("Bad read in readrec, %ld", dp) ;
  1536.       }
  1537.       if (bfr[0] != (char)A_PREFIX) {
  1538.             printf("len=%d, dp=%ld\n", len, (long)dp);
  1539.             fprintf(stderr, "bfr: %o %o %o %o %o\n", bfr[0], bfr[1],
  1540. bfr[2], bfr[3], bfr[4]);
  1541.             fprintf(stderr, "A_PREFIX = %o, (char)A_PREFIX = %o\n", A_PREFIX, (char)A_PREFIX);
  1542.             xerror("bad article pointer %ld", dp) ;
  1543.       }
  1544.       bcopy(bfr + 1, (char *)a, A_WRTLEN) ;
  1545.       bcopy(bfr + 1 + A_WRTLEN, (char *)a->a_group, i = a->a_ngroups * sizeof(*a->a_group)) ;
  1546.       pp = &a->a_ident ;
  1547.       p = bfr + 1 + A_WRTLEN + i ;
  1548.       q = a->a_space ;
  1549.       len -= 1 + A_WRTLEN + i ;
  1550.       i = (a->a_flags & A_DUMMY)? 1 : 4 + a->a_nkwords ;
  1551.       while (--i >= 0) {
  1552.             *pp++ = q ;
  1553.             do if (--len < 0) {
  1554.                   read(affd, bfr, 512) ;
  1555.                   len = 512 ;
  1556.                   p = bfr ;
  1557.                }
  1558.             while (*q++ = *p++) ;
  1559.       }
  1560. }
  1561.  
  1562.  
  1563.  
  1564. /*
  1565.  * Read a pointer from the article file
  1566.  */
  1567.  
  1568. DPTR
  1569. readptr(dp)
  1570.       DPTR dp ;
  1571.       {
  1572.       DPTR new ;
  1573.  
  1574.       if (lseek(affd, (long)dp, 0) < 0)
  1575.             xerror("seek %ld failed, readptr\n", dp) ;
  1576.       if (read(affd, (char *)&new, sizeof(new)) != sizeof(new))
  1577.             xerror("read failed, readptr(%ld)\n", dp) ;
  1578.       return new ;
  1579. }
  1580. !E!O!F!
  1581.  
  1582. cat > lib/readinrc.c <<\!E!O!F!
  1583. /*
  1584.  * Read in the .newsrc file and the newsgroups file.  If rcfp is NULL,
  1585.  * only the newsgroups file is read.
  1586.  */
  1587.  
  1588. #include <stdio.h>
  1589. #include <sys/types.h>
  1590. #include <sys/stat.h>
  1591. #include <ctype.h>
  1592. #include "defs.h"
  1593. #include "artfile.h"
  1594. #include "ng.h"
  1595. #include "newsrc.h"
  1596. #include "libextern.h"
  1597. #include "str.h"
  1598.  
  1599. static int rcmode;        /* file modes for .newsrc file */
  1600. int rcreadok;            /* .newsrc file has been read */
  1601. int rcsaved;            /* .newsrc file has been backed up */
  1602. char *rcjunk[MAXRCJUNK];    /* comment lines in .newsrc file */
  1603. char **nextrcjunk = rcjunk;    /* first unused entry in rcjunk */
  1604. struct ngentry ngtable[MAXGROUPS];    /* newsgroup table */
  1605. int ndunsub;            /* number of discussions unsubscribed to */
  1606. DPTR dunsub[MAXUNSUB];        /* discussions unsubscribed to */
  1607. struct ngentry *firstng, *lastng;    /* articles in .newsrc file */
  1608. struct ngentry *curng;        /* current newsgroup */
  1609.  
  1610. struct ngentry **nghashtab, *hashng();
  1611.  
  1612.  
  1613. readinrc(rcfp)
  1614.     FILE *rcfp;
  1615.     {
  1616.     register struct ngentry *ngp;
  1617.     register char *p;
  1618.     char unsub;
  1619.     int i;
  1620.     DPTR dp;
  1621.     struct artrec a;
  1622.     struct ngrec g;
  1623.     struct stat statb;
  1624.  
  1625.     gfopen();
  1626.     if (maxng >= MAXGROUPS)
  1627.         xerror("Too many groups, increase MAXGROUPS");
  1628.     nghashtab = ckmalloc(i = (MAXGROUPS * 2 + 1) * sizeof *nghashtab);
  1629.     bzero((char *)nghashtab, i);
  1630.     ALL_GROUPS(g) {
  1631.         ngtable[g.g_num].ng_name = nsavestr(g.g_name);
  1632.         hashng(g.g_name, &ngtable[g.g_num]);
  1633.     }
  1634.     gfclose();
  1635.     if (rcfp == NULL)
  1636.         goto out;
  1637.     if (fstat(fileno(rcfp), &statb) >= 0)
  1638.         rcmode = statb.st_mode;
  1639.     while (fgets(bfr, LBUFLEN, rcfp) != NULL) {
  1640.         if (!nstrip(bfr))
  1641.             xerror(".newsrc line too long");
  1642.         if (bfr[0] == '<') {
  1643.             char ident[NAMELEN];
  1644.             scopyn(bfr, ident, NAMELEN);
  1645.             if (ndunsub >= MAXUNSUB)
  1646.                 xerror("Unsubscribed to too many discussions");
  1647.             if ((dp = lookart(ident, &a)) != DNULL)
  1648.                 dunsub[ndunsub++] = dp;
  1649.         } else if (islower(bfr[0])) {        /* newsgroup line? */
  1650.             for (p = bfr ; *p != ':' && *p != '!' ; p++)
  1651.                 if (*p == '\0' || *p == ' ' || *p == '\t')
  1652.                     goto junk;
  1653.             unsub = (*p == '!');
  1654.             *p++ = '\0';
  1655.             if (*p == ' ')
  1656.                 p++;
  1657.             ngp = hashng(bfr, (struct ngentry *)0);
  1658.             if (ngp != NULL) {
  1659.                 if (ngp->ng_bits != NULL) {
  1660.                     free(ngp->ng_bits);
  1661.                 } else {
  1662.                     addrc(ngp);
  1663.                 }
  1664.                 ngp->ng_bits = savestr(p);
  1665.                 ngp->ng_unsub = unsub;
  1666.             }
  1667.         } else {
  1668. junk:            if (nextrcjunk >= &rcjunk[MAXRCJUNK])
  1669.                 xerror("Too many lines in .newsrc");
  1670.             *nextrcjunk++ = savestr(bfr);
  1671.         }
  1672.     }
  1673.     free(nghashtab);
  1674.     rcreadok = 1;
  1675.  
  1676. out:
  1677.     /* add new groups to the .newsrc file */
  1678.     for (ngp = ngtable ; ngp < ngtable + MAXGROUPS ; ngp++) {
  1679.         if (ngp->ng_name != NULL && ngp->ng_bits == NULL && wewant(ngp->ng_name))
  1680.             addrc(ngp);
  1681.     }
  1682. }
  1683.  
  1684.  
  1685.  
  1686. /*
  1687.  * Write out the .newsrc file.
  1688.  */
  1689. writeoutrc()
  1690. {
  1691.     FILE *rcfp;
  1692.     register int i;
  1693.     char **jp;
  1694.     struct ngentry *ngp;
  1695.     char newstmp[FPATHLEN];
  1696.     char newsbak[FPATHLEN];
  1697.     struct artrec a;
  1698.     FILE *ckfopen();
  1699.  
  1700.     if (!rcreadok)
  1701.         return;
  1702.     updaterc();
  1703.     sprintf(newstmp, "%s.tmp", newsrc);
  1704.     rcfp = ckfopen(newstmp, "w");
  1705.     if (rcmode)
  1706.         chmod(newstmp, rcmode);
  1707.  
  1708.     /* Write out options line, continuations, and comments. */
  1709.     for (jp = rcjunk ; jp < nextrcjunk ; jp++)
  1710.         fprintf(rcfp, "%s\n", *jp);
  1711.  
  1712.     /* Write out the newsgroup lines. */
  1713.     for (ngp = firstng ; ngp != NULL ; ngp = ngp->ng_next) {
  1714.         fprintf(rcfp, "%s%c", ngp->ng_name, ngp->ng_unsub? '!' : ':');
  1715.         if (ngp->ng_bits != NULL && *ngp->ng_bits != '\0')
  1716.             fprintf(rcfp, " %s", ngp->ng_bits);
  1717.         putc('\n', rcfp);
  1718.     }
  1719.     /* write out a list of discussions we have unsubscribed to */
  1720.     for (i = 0 ; i < ndunsub ; i++) {
  1721.         readrec(dunsub[i], &a);
  1722.         fprintf(rcfp, "%s\n", a.a_ident);
  1723.     }
  1724.     if (ferror(rcfp) || fclose(rcfp) == EOF)
  1725.         xerror("write error on .newsrc.tmp");
  1726.     sprintf(newsbak, "%s.bak", newsrc);
  1727.     if (! rcsaved) {
  1728.         rename(newsrc, newsbak);
  1729.         rcsaved++;
  1730.     }
  1731.     if (rename(newstmp, newsrc) < 0)
  1732.         xerror("rename .newsrc.tmp to .newsrc failed");
  1733. }
  1734.  
  1735.  
  1736. struct ngentry *
  1737. hashng(name, entry)
  1738.       char *name;
  1739.       struct ngentry *entry;
  1740.       {
  1741.       register char *p;
  1742.       register int i;
  1743.       register struct ngentry *ngp;
  1744.  
  1745.       i = 0;
  1746.       for (p = name ; *p ; i += *p++);
  1747.       if (p > name + 2)
  1748.             i += (p[-2] << 2) + (p[-1] << 1);
  1749.       i &= 077777;            /* protect against negetive chars */
  1750.       for (i = i % (MAXGROUPS * 2 + 1) ; (ngp = nghashtab[i]) != NULL ; ) {
  1751.             if (strcmp(ngp->ng_name, name) == 0)
  1752.                   return ngp;
  1753.             if (++i >= (MAXGROUPS * 2 + 1))
  1754.                   i = 0;
  1755.       }
  1756.       if (entry != NULL)
  1757.             nghashtab[i] = entry;
  1758.       return ngp;
  1759. }
  1760. !E!O!F!
  1761.  
  1762. cat > lib/rename.c <<\!E!O!F!
  1763. #include <errno.h>
  1764. #include "config.h"
  1765.  
  1766. #if BSDREL < 42
  1767.  
  1768. int
  1769. rename(from, to)
  1770.       char *from, *to ;
  1771.       {
  1772.       extern int errno ;
  1773.  
  1774.       if (link(from, to) < 0) {
  1775.             if (errno != EEXIST)
  1776.                   return -1 ;
  1777.             if (unlink(to) < 0 || link(from, to) < 0)
  1778.                   return -1 ;
  1779.       }
  1780.       return unlink(from) ;
  1781. }
  1782.  
  1783. #endif
  1784. !E!O!F!
  1785.  
  1786. cat > lib/replyname.c <<\!E!O!F!
  1787. /*
  1788.  * Generate an address for replying to this article
  1789.  */
  1790.  
  1791. #include <stdio.h>
  1792. #include "config.h"
  1793. #include "defs.h"
  1794. #include <sys/types.h>
  1795. #include "arthead.h"
  1796.  
  1797. char *
  1798. replyname(hptr, tbuf)
  1799. struct arthead *hptr;
  1800. char tbuf[PATHLEN];
  1801. {
  1802.     register char *ptr;
  1803.     extern char FULLSYSNAME[];
  1804.     char *getaddr();
  1805.  
  1806. #ifndef INTERNET
  1807.     strcpy(tbuf, hptr->h_path);
  1808.     /*
  1809.      * Play games stripping off multiple berknet
  1810.      * addresses (a!b!c:d:e => a!b!d:e) here.
  1811.      */
  1812.     for (ptr=tbuf; *ptr; ptr++)
  1813.         if (index(NETCHRS, *ptr) && *ptr == ':' && index(ptr+1, ':'))
  1814.             strcpy(ptr, index(ptr+1, ':'));
  1815. #else
  1816.     ptr = hptr->h_from;
  1817.     if (hset(hptr->h_replyto))
  1818.         ptr = hptr->h_replyto;
  1819.     getaddr(ptr, tbuf);
  1820. #endif
  1821.     return tbuf;
  1822. }
  1823. !E!O!F!
  1824.  
  1825. cat > lib/rewinddir.c <<\!E!O!F!
  1826. #include "config.h"
  1827. #if BSDREL < 42
  1828. #include <sys/types.h>
  1829. #include <sys/param.h>
  1830. #include "ndir.h"
  1831.  
  1832. /*
  1833.  * Go back to the beginning of a directory.
  1834.  */
  1835.  
  1836. rewinddir(dirp)
  1837.     DIR *dirp;
  1838.     {
  1839.     dirp->dd_nleft = 0;
  1840.     lseek(dirp->dd_fd, 0L, 0);
  1841. }
  1842. #endif
  1843. !E!O!F!
  1844.  
  1845. cat > lib/rmnf.c <<\!E!O!F!
  1846. /*
  1847.  * Zap the notesfile indicator.
  1848.  */
  1849.  
  1850. #define equal(s1, s2)    (strcmp(s1, s2) == 0)
  1851.  
  1852. rmnf(title)
  1853.       char *title ;
  1854.       {
  1855.       register char *p ;
  1856.  
  1857.       p = title + strlen(title) - 7 ;
  1858.       if (p > title && equal(p, " - (nf)")) {
  1859.             *p = '\0' ;
  1860.             return 1 ;
  1861.       }
  1862.       return 0 ;
  1863. }
  1864. !E!O!F!
  1865.  
  1866. cat > lib/roptions.c <<\!E!O!F!
  1867. #include <stdio.h>
  1868. #include "config.h"
  1869. #include "defs.h"
  1870. #include "roptions.h"
  1871.  
  1872.  
  1873. char *savestr(), *getenv(), *index(), *hfgets();
  1874.  
  1875.  
  1876. struct optable options[] = { /*
  1877. optlet    filchar    flag    newstate oldmode    newmode    buf    */
  1878. 'p',    '\0',    FALSE,    OPTION,    UNKNOWN,    UNKNOWN,NULL,    
  1879. 't',    '\1',    FALSE,    STRING,    ANY,        UNKNOWN,NULL,
  1880. 'a',    ' ',    FALSE,    STRING,    ANY,        UNKNOWN,NULL,
  1881. 'n',   NGDELIM,    FALSE,    STRING,    ANY,        UNKNOWN,NULL,
  1882. 'c',    ' ',    FALSE,    STRING,    UNKNOWN,    UNKNOWN,NULL,
  1883. 'l',    ' ',    FALSE,    OPTION,    UNKNOWN,    UNKNOWN,NULL,
  1884. 'r',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1885. /* the s option used to read a list of newsgroups.  Not any more */
  1886. 's',   NGDELIM,    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1887. 'x',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1888. 'h',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1889. 'M',    '\0',    FALSE,    OPTION,    UNKNOWN,    MAIL,    NULL,
  1890. 'f',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1891. 'u',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1892. 'e',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1893. '1',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1894. '2',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1895. 'A',    '\0',    FALSE,    OPTION,    ANY,        UNKNOWN,NULL,
  1896. '\0',    '\0',    0,    0,    0,        0,    NULL
  1897. };
  1898.  
  1899. char *progname ;
  1900. char *titles[10] ;        /* list of titles */
  1901. extern char bfr[] ;
  1902.  
  1903.  
  1904. roptions(argv, rcfp)
  1905.       char **argv ;
  1906.       FILE *rcfp ;
  1907.       {
  1908.       char *p ;
  1909.       char **pp ;
  1910.  
  1911.       progname = *argv++ ;
  1912.       if ((p = getenv("NEWSOPTS")) != NULL) {
  1913.             scopyn(p, bfr, LBUFLEN - 2) ;
  1914.             procostr(bfr) ;
  1915.       }
  1916.       if (rcfp != NULL && hfgets(bfr, LBUFLEN - 2, rcfp) != NULL && prefix(bfr, "options ")) {
  1917.             procostr(bfr + 8) ;
  1918.       }
  1919.       if (sublist == NULL)
  1920.             sublist = savestr(DFLTSUB);
  1921. #ifdef ADMSUB
  1922.       sprintf(bfr, "%s,%s", sublist, ADMSUB);
  1923.       free(sublist);
  1924.       sublist = savestr(bfr);
  1925. #endif
  1926.  
  1927.       procopt(argv) ;
  1928.  
  1929.       if (cflag) {
  1930.             oneflag = FALSE;
  1931.             twoflag = TRUE;
  1932.       }
  1933.       if (pflag) {
  1934.             oneflag = FALSE;
  1935.             twoflag = FALSE;
  1936.       }
  1937.       if (!oneflag && !twoflag && !pflag) {
  1938.             oneflag = TRUE;
  1939.             twoflag = TRUE;
  1940.       }
  1941.       if (oneflag && !twoflag)
  1942.             cflag = 1;
  1943.       strcpy(bfr, sublist);
  1944.       makehimask(bfr, "junk");
  1945.       makehimask(bfr, "control");
  1946.       /* makehimask(bfr, "test"); */
  1947.       free(sublist);
  1948.       sublist = savestr(bfr);
  1949.       if (toptbuf) {
  1950.             pp = titles ;
  1951.             p = toptbuf ;
  1952.             for (;;) {
  1953.                   if (pp >= titles + 9)
  1954.                         xerror("Too many titles") ;
  1955.                   *pp++ = p ;
  1956.                   if ((p = index(p, '\1')) == NULL)
  1957.                         break ;
  1958.                   *p++ = '\0' ;
  1959.             }
  1960.       }
  1961. }
  1962. !E!O!F!
  1963.  
  1964. cat > lib/roptions.h <<\!E!O!F!
  1965. /* flags for readnews */
  1966. #define pflag    options[0].flag
  1967. #define tflag    options[1].flag
  1968. #define toptbuf    options[1].buf
  1969. #define aflag    options[2].flag
  1970. #define datebuf    options[2].buf
  1971. #define nflag    options[3].flag
  1972. #define sublist    options[3].buf
  1973. #define cflag    options[4].flag
  1974. #define coptbuf    options[4].buf
  1975. #define lflag    options[5].flag
  1976. #define rflag    options[6].flag
  1977. #define sflag    options[7].flag
  1978. #define xflag    options[8].flag
  1979. #define hflag    options[9].flag
  1980. #define Mflag    options[10].flag
  1981. #define fflag    options[11].flag
  1982. #define uflag    options[12].flag
  1983. #define eflag    options[13].flag
  1984. #define oneflag    options[14].flag
  1985. #define twoflag    options[15].flag
  1986. #define Aflag    options[16].flag
  1987.  
  1988. #define UNKNOWN 0001    /* possible modes for news program */
  1989. #define MAIL    0004
  1990. #define ANY    0007
  1991.  
  1992. #define OPTION    0    /* pick up an option string */
  1993. #define STRING    1    /* pick up a string of arguments */
  1994.  
  1995. struct optable {            /* options table. */
  1996.     char    optlet;        /* option character. */
  1997.     char    filchar;    /* if to pickup string, fill character. */
  1998.     int    flag;        /* TRUE if have seen this opt. */
  1999.     int    newstate;    /* STRING if takes arg, else OPTION */
  2000.     int    oldmode;    /* OR of legal input modes. */
  2001.     int    newmode;    /* output mode. */
  2002.     char    *buf;        /* string buffer */
  2003. };
  2004.  
  2005. extern struct optable options[];
  2006. extern int mode;
  2007. !E!O!F!
  2008.  
  2009. cat > lib/savestr.c <<\!E!O!F!
  2010. /*
  2011.  * Make a copy of a string
  2012.  */
  2013.  
  2014. char
  2015. *savestr(s)
  2016.       char *s ;
  2017.       {
  2018.       char *p ;
  2019.       char *ckmalloc() ;
  2020.  
  2021.       p = ckmalloc(strlen(s) + 1) ;
  2022.       strcpy(p, s) ;
  2023.       return p ;
  2024. }
  2025. !E!O!F!
  2026.  
  2027. cat > lib/schar.c <<\!E!O!F!
  2028. /*
  2029.  * Convert a character to an integer, performing sign extension even on
  2030.  * machines that don't provide hardware support for signed characters.
  2031.  * This routine should be replaced by the macro
  2032.  *    #define schar(c)    ((char)(c))
  2033.  * for compilers that support signed characters.
  2034.  */
  2035.  
  2036. /* The high bit of a character */
  2037. #define SIGNBIT (int)((unsigned char)(-1) &~ ((unsigned char)(-1) >> 1))
  2038. #define EXTBITS (int)(-1 &~ (unsigned char)(-1))
  2039.  
  2040. int
  2041. schar(c)
  2042.       char c ;
  2043.       {
  2044.       return (c & SIGNBIT) ? c | EXTBITS : c ;
  2045. }
  2046. !E!O!F!
  2047.  
  2048. cat > lib/scopyn.c <<\!E!O!F!
  2049. scopyn(from, to, n)
  2050.       register char *from, *to ;
  2051.       register int n ;
  2052.       {
  2053.       while (--n > 0 && (*to++ = *from++) != '\0') ;
  2054.       *to = '\0' ;
  2055. }
  2056. !E!O!F!
  2057.  
  2058. cat > lib/scopyn.pdp <<\!E!O!F!
  2059. / SCOPYN(FROM, TO, N)  CHAR *FROM, *TO;
  2060. /
  2061. /    Copy string "from" to string "to", truncating "to" to n - 1
  2062. /    characters to avoid overflow.
  2063. /
  2064.  
  2065. .globl    _scopyn
  2066.  
  2067. _scopyn:
  2068.     mov  sp, r0            / prepare to access args
  2069.     mov  r2, -(sp)            / save r2
  2070.     tst  (r0)+            /
  2071.     mov  (r0)+, r1            / get from
  2072.     mov  (r0)+, r2            / get to
  2073.     mov  (r0)+, r0            / get n
  2074.     br   2f                / enter middle of loop
  2075. 1:    movb (r1)+, (r2)+        /   copy a byte
  2076.     beq  3f                /   until a nul is encountered
  2077. 2:    sob  r0, 1b            /   or count is exhausted
  2078. 3:    clrb (r2)            / nul terminate "to" string
  2079.     mov  (sp)+, r2            / restore r2
  2080.     rts  pc                / and return
  2081. !E!O!F!
  2082.  
  2083. cat > lib/scopyn.u3b <<\!E!O!F!
  2084.     .file "scopyn.u3b"        # give me a break!
  2085.     .globl    scopyn
  2086.     .align    4
  2087. scopyn:    save    &1            # save r8
  2088.     movw    0(%ap), %r0        # get from
  2089.     movw    4(%ap), %r1        # get to
  2090.     subw3    &1, 8(%ap), %r2        # get count - 1 to leave room for nul
  2091.     movw    &0, %r8            # string terminator
  2092.     movcce    %r0, %r2, %r1, %r8    # copy the string
  2093.     movb    &0, 0(%r1)        # append nul terminator
  2094.     ret    &1            # and return
  2095. !E!O!F!
  2096.  
  2097. cat > lib/scopyn.vax <<\!E!O!F!
  2098. # SCOPYN(SRC, DEST, N)  CHAR *SRC, *DEST
  2099. #
  2100. #    Copy src to dest, truncating the source string to n - 1 charaters
  2101. #    if necessary.  Dest will always get a nul terminator.
  2102. #
  2103.     .globl    _scopyn
  2104.     .align    2
  2105. _scopyn:.word    0            # no registers saved
  2106.     movq    4(ap), r4        # get src and dest
  2107.     subl3    $1, 12(ap), r0        # get n, leaving space for nul
  2108.     locc    $0, r0, (r4)        # scan until nul or count exhausted
  2109.     subl2    r4, r1            # find length
  2110.     movc3    r1, (r4), (r5)        # move the characters
  2111.     clrb    (r3)            # nul terminate dest
  2112.     ret                # and return
  2113. !E!O!F!
  2114.  
  2115. cat > lib/setup <<\!E!O!F!
  2116. #!/bin/sh
  2117.  
  2118. : This shell procedure reads in the config file, generates defaults for
  2119. : all the values not specified, and generated the config.h, newsdefs.h,
  2120. : makedefs, and archive.  It should be run to bring up a new system.
  2121. :
  2122. : This shell procedure uses the value ",,,," to indicate that a variable
  2123. : has not been set.
  2124.  
  2125. exec 3<&0
  2126. if test ! -f config
  2127. then    echo "Please create config file and run again."
  2128.     exit 1
  2129. fi
  2130.  
  2131. : figure out who is running this program
  2132. user=${LOGNAME-${USER-,,,,}}
  2133. if test "$user" = ,,,,
  2134. then    ls -l config > junk
  2135.     exec < junk
  2136.     read x y user rest
  2137.     rm -f junk
  2138.     if test "$user" = ""
  2139.     then     user=news
  2140.     fi
  2141. fi
  2142.  
  2143. : look for other setup programs
  2144. setups= special=
  2145. for x in ../*
  2146. do    if test -f $x/config.parms
  2147.     then    setups="$setups $x/setup"
  2148.         special="$special`cat $x/config.parms`
  2149. "
  2150.     fi
  2151. done
  2152.  
  2153. : set up all the defaults
  2154. lib=/usr/lib/news
  2155. spool=/usr/spool/news
  2156. bin=/usr/bin
  2157. admin=,,,,
  2158. compadmin=no
  2159. newsusr=,,,,
  2160. newsgrp=,,,,
  2161. home=,,,,
  2162. sys=,,,,
  2163. cpu=,,,,
  2164. small=,,,,
  2165. umask=000
  2166. dftexp=14
  2167. tmail=,,,,
  2168. mailer=,,,,
  2169. dftsub=all
  2170. admsub=general,all.announce
  2171. page=,,,,
  2172. notify=,,,,
  2173. dfteditor=,,,,
  2174. manually=
  2175. internet=
  2176. mydomain=,,,,
  2177. myname=,,,,
  2178. myorg=,,,,
  2179. sendmail=,,,,
  2180. uname=,,,,
  2181. ghname=,,,,
  2182. v7mail=
  2183. newsrc=.newsrc
  2184. maxgroups=350
  2185. buflen=,,,,
  2186. lbuflen=1024
  2187. pathlen=512
  2188. datelen=48
  2189. namelen=64
  2190. fpathlen=64
  2191. termcap=,,,,
  2192.  
  2193. : read in the config file
  2194. exec <config
  2195. while read name value
  2196. do    case $name in
  2197.     path)        PATH=$value ;;
  2198.     lib)        lib=$value ;;
  2199.     spool)        spool=$value ;;
  2200.     bin)        bin=$value ;;
  2201.     admin)        admin=$value ;;
  2202.     compadmin)    compadmin=$value ;;
  2203.     newsusr)    newsusr=$value ;;
  2204.     newsgrp)    newsgrp=$value ;;
  2205.     home)        home=$value ;;
  2206.     sys)        sys=$value ;;
  2207.     cpu)        cpu=$value ;;
  2208.     small)        small=$value ;;
  2209.     umask)        umask=$value ;;
  2210.     dftexp)        dftexp=$value ;;
  2211.     tmail)        tmail=$value ;;
  2212.     mailer)        mailer=$value ;;
  2213.     dftsub)        dftsub=$value ;;
  2214.     dfltsub)    dftsub=$value ;;
  2215.     admsub)        admsub=$value ;;
  2216.     page)        page=$value ;;
  2217.     notify)        notify=$value ;;
  2218.     dfteditor)    dfteditor=$value ;;
  2219.     manually)    manually=$value ;;
  2220.     internet)    internet=$value ;;
  2221.     mydomain)    mydomain=$value ;;
  2222.     myname)        myname=$value ;;
  2223.     myorg)        myorg=$value ;;
  2224.     uname)        uname=$value ;;
  2225.     ghname)        ghname=$value ;;
  2226.     v7mail)        v7mail=$value ;;
  2227.     newsrc)        newsrc=$value ;;
  2228.     maxgroups)    maxgroups=$value ;;
  2229.     buflen)        buflen=$value ;;
  2230.     lbuflen)    lbuflen=$value ;;
  2231.     pathlen)    pathlen=$value ;;
  2232.     datelen)    datelen=$value ;;
  2233.     namelen)    namelen=$value ;;
  2234.     fpathlen)    fpathlen=$value ;;
  2235.     termcap)    termcap=$value ;;
  2236.     "")    ;;
  2237.     "#"*)    ;;
  2238.     *)    for x in $special
  2239.         do    if test "$name" = "$x"
  2240.             then    name=
  2241.             fi
  2242.         done
  2243.         if test "$name" != ""
  2244.         then    echo "Unknown config keyword:  $name"
  2245.             exit 2
  2246.         fi
  2247.         ;;
  2248.     esac
  2249. done
  2250.  
  2251. if test "$sys" = ,,,,
  2252. then    if test -f /usr/include/termio.h
  2253.     then    if test -f /bin/shl -o -f /usr/bin/shl
  2254.         then    sys=sys5r2
  2255.         elif test -f /usr/bin/cflow
  2256.         then    sys=sys5
  2257.         else    sys=sys3
  2258.         fi
  2259.     else    if test -f /usr/include/sys/time.h
  2260.         then    sys=4.2bsd
  2261.         elif test -d /usr/ucb
  2262.         then    sys=4.1bsd
  2263.         else    sys=v7
  2264.         fi
  2265.     fi
  2266.     echo system assumed to be $sys.
  2267. fi
  2268.  
  2269. case "$sys" in
  2270. sys3)    USGREL=30 BSDREL=6 ;;
  2271. sys5)    USGREL=50 BSDREL=6 ;;
  2272. sys5r2)    USGREL=52 BSDREL=6 ;;
  2273. v7)    BSDREL=7  USGREL=6 ;;
  2274. 4.1bsd)    BSDREL=41 USGREL=6 ;;
  2275. 4.2bsd) BSDREL=42 USGREL=6 ;;
  2276. *)    echo "Unknown system type $sys"
  2277.     exit 1 ;;
  2278. esac
  2279.  
  2280. if test "$cpu" = ,,,,
  2281. then    cc -P cpu.c
  2282.     cpu=`sed -n s/X//p cpu.i`
  2283.     /bin/rm -f cpu.i
  2284. fi
  2285. case "$cpu" in
  2286. pdp11|vax|u3b|other) ;;
  2287. "")    cpu=other ;;
  2288. *)    echo "Unknown cpu type $cpu"
  2289.     exit 1
  2290.     ;;
  2291. esac
  2292.  
  2293. if test "$small" = ,,,, -a $cpu = pdp11
  2294. then    small=yes
  2295. fi
  2296. if test "$buflen" = ,,,,
  2297. then    if test "$small" = "no" -o "$small" = ,,,,
  2298.     then    buflen=256
  2299.     else    buflen=128
  2300.     fi
  2301. fi
  2302.  
  2303. if test "$uname" = ,,,, -a $USGREL -ge 20
  2304. then    uname=yes
  2305. fi
  2306. if test "$ghname" = ,,,, -a $BSDREL -ge 42
  2307. then    ghname=yes
  2308. fi
  2309.  
  2310. : check all the boolean flags
  2311. for x in manually internet uname ghname v7mail small compadmin
  2312. do    eval y=\$$x
  2313.     case "$y" in
  2314.     no|,,,,)eval $x=,,,, ;;
  2315.     ""|yes)    eval $x= ;;
  2316.     *)    echo $x is a boolean flag.
  2317.         exit 1 ;;
  2318.     esac
  2319. done
  2320.  
  2321. : check that all numeric parameters are set and are numbers
  2322. for x in umask dftexp maxgroups buflen lbuflen pathlen datelen namelen fpathlen
  2323. do    eval y=\$$x
  2324.     case "$y" in
  2325.     [0-9]|[0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9]) ;;
  2326.     ,,,,)    echo "$x not set"
  2327.         exit 1 ;;
  2328.     *)    echo "$x value should be numeric"
  2329.         exit 1 ;;
  2330.     esac
  2331. done
  2332.  
  2333. : Check that required values are specified
  2334. for x in myorg mydomain newsusr newsgrp
  2335. do    eval y=\$$x
  2336.     if test "$y" = ,,,,
  2337.     then    echo $x not set
  2338.         exit 1
  2339.     fi
  2340. done
  2341.  
  2342. case "$mydomain" in
  2343. ""|.*)    ;;
  2344. *)    echo domain name should begin with a dot.
  2345.     exit 1 ;;
  2346. esac
  2347.  
  2348. if test "$admin" = ,,,,
  2349. then    admin=$user
  2350. fi
  2351. if test "$notify" = ""
  2352. then    notify=$admin
  2353. fi
  2354. if test "$termcap" = ,,,,
  2355. then    if test -f /usr/lib/libtermcap.a
  2356.     then    termcap=-ltermcap
  2357.     elif test -f /usr/lib/libtermlib.a
  2358.     then    termcap=-ltermlib
  2359.     elif test -f /usr/lib/libcurses.a
  2360.     then    termcap=-lcurses
  2361.     else    termcap=-ltermcap
  2362.     fi
  2363. fi
  2364. if test "$sendmail" = ,,,,
  2365. then    if test -f /usr/lib/sendmail
  2366.     then    sendmail=/usr/lib/sendmail
  2367.     fi
  2368. fi
  2369.  
  2370. : on BSD systems, prefer /bin/mail over /usr/ucb/mail
  2371. if test "$mailer" = ,,,, -a -f /bin/mail
  2372. then    mailer=/bin/mail
  2373. fi
  2374.  
  2375. : do some path searches
  2376. y=
  2377. for x in page more page pg dfteditor vi dfteditor ed mailer mail
  2378. do    if test "$y" = ""
  2379.     then    y=$x
  2380.     else    eval v=\$$y
  2381.         if test "$v" = ,,,,
  2382.         then    IFS=:
  2383.             for z in $PATH
  2384.             do    if test -f $z/$x
  2385.                 then    eval $y=$z/$x
  2386.                     break
  2387.                 fi
  2388.             done
  2389.             IFS='     
  2390. '
  2391.         fi
  2392.         y=
  2393.     fi
  2394. done
  2395.  
  2396. if test "$mailer" = ,,,
  2397. then    echo Can\'t find mail
  2398.     exit 1
  2399. fi
  2400. if test "$dfteditor" = ,,,,
  2401. then    echo Can\'t find ed
  2402.     exit 1
  2403. fi
  2404.  
  2405. for x in admsub page sendmail
  2406. do    eval y=\$$x
  2407.     if test "$y" = ""
  2408.     then    eval $x=,,,,
  2409.     fi
  2410. done
  2411.  
  2412. if test "$compadmin" = ""
  2413. then    adminid=,,,,
  2414. else    adminid=`sed -n "s/^$admin:[^:]*:\([^:]*\):.*/\1/p" /etc/passwd`
  2415.     if test "$adminid" = ""
  2416.     then    echo Can\'t find $admin in /etc/passwd file.
  2417.         exit 1
  2418.     fi
  2419. fi
  2420.  
  2421. : 2.10.2 moved inews [Grrr!]
  2422. if test -f $lib/inews
  2423. then    inews=$lib/inews
  2424. else    inews=$bin/inews
  2425. fi
  2426.  
  2427. if test $USGREL -ge 30
  2428. then    index=strchr
  2429.     rindex=strrchr
  2430.     usg=
  2431. else    index=,,,,
  2432.     rindex=,,,,
  2433.     usg=,,,,
  2434. fi
  2435.  
  2436. grep -v ,,,, > config.h.tmp <<!
  2437. #define USGREL $USGREL
  2438. #define BSDREL $BSDREL
  2439. #define USG$usg
  2440. #define SMALL$small
  2441. #define index $index
  2442. #define rindex $rindex
  2443. !
  2444.  
  2445. grep -v ,,,, > newsdefs.h.tmp <<!
  2446. /*
  2447.  * newsdefs.h - defines for news related programs.
  2448.  *
  2449.  * This file is created by the setup program, and should be changed
  2450.  * by modifying the entries in config.
  2451.  */
  2452.  
  2453. #define N_UMASK    $umask
  2454. #define DFLTEXP    ($dftexp*24L*3600L)
  2455. #define DFTEDITOR "$dfteditor"
  2456. #define    DFLTSUB    "$dftsub"
  2457. #define ADMSUB    "$admsub"
  2458. #define PAGE    "$page"
  2459. #define TMAIL    "$tmail"
  2460. #define MAILER    "$mailer"
  2461. #define INEWS    "$inews"
  2462. #define RNEWS    "$bin/rnews"
  2463. #define POSTNM    "$bin/postnm"
  2464. #define LIBDIR    "$lib
  2465. #define SPOOLDIR "$spool
  2466. #define BINDIR    "$bin
  2467. #define HOME    "$home"
  2468. #define NOTIFY    "$notify"
  2469. #define ADMIN    "$admin"
  2470. #define ROOTID    $adminid
  2471. #define MANUALLY$manually
  2472. #define INTERNET$internet
  2473. #define MYDOMAIN "$mydomain"
  2474. #define MYNAME    "$myname"
  2475. #define UNAME$uname
  2476. #define GHNAME$ghname
  2477. #define SENDMAIL "$sendmail"
  2478. #define V7MAIL$v7mail
  2479. #define MYORG    "$myorg"
  2480. #define NEWSRC    "$newsrc"
  2481. #define MAXGROUPS $maxgroups
  2482. #define BUFLEN    $buflen
  2483. #define LBUFLEN    $lbuflen
  2484. #define PATHLEN    $pathlen
  2485. #define DATELEN    $datelen
  2486. #define NAMELEN    $namelen
  2487. #define FPATHLEN $fpathlen
  2488. !
  2489.  
  2490. if test "$home" != ,,,,
  2491. then    hdir=`logdir $home`/
  2492. else    hdir=
  2493. fi
  2494.  
  2495. grep -v ,,,, > makedefs.tmp <<!
  2496. LIBDIR=$hdir$lib
  2497. SPOOLDIR=$hdir$spool
  2498. BINDIR=$bin
  2499. NEWSUSR=$newsusr
  2500. NEWSGRP=$newsgrp
  2501. HOME=$home
  2502. CPU=$cpu
  2503. USGREL=$USGREL
  2504. BSDREL=$BSDREL
  2505. TERMCAP=$termcap
  2506. !
  2507.  
  2508. if cmp -s config.h.tmp config.h
  2509. then    /bin/rm config.h.tmp
  2510. else    /bin/mv config.h.tmp config.h
  2511. fi
  2512. if cmp -s newsdefs.h.tmp newsdefs.h
  2513. then    /bin/rm newsdefs.h.tmp
  2514. else    /bin/mv newsdefs.h.tmp newsdefs.h
  2515. fi
  2516. if cmp -s makedefs.tmp makedefs
  2517. then    /bin/rm makedefs.tmp
  2518. else    /bin/mv makedefs.tmp makedefs
  2519. fi
  2520.  
  2521. for x in $setups
  2522. do    $x -M
  2523. done
  2524. echo 'The modified time of this file indicates when setup was last run.' > setuptime
  2525.  
  2526. sed -e 's/B,,,,/no/' -e 's/B$/yes/' -e '/,,,,/s/^/#/' -e 's/[     ],,,,//' > config.used <<!
  2527. path    $PATH
  2528. lib    $lib
  2529. spool    $spool
  2530. bin    $bin
  2531. admin    $admin
  2532. compadmin B$compadmin
  2533. newsusr    $newsusr
  2534. newsgrp    $newsgrp
  2535. home    $home
  2536. sys    $sys
  2537. cpu    $cpu
  2538. small    B$small
  2539. umask    $umask
  2540. dftexp    $dftexp
  2541. tmail    $tmail
  2542. mailer    $mailer
  2543. dftsub    $dftsub
  2544. admsub    $admsub
  2545. page    $page
  2546. notify    $notify
  2547. dfteditor $dfteditor
  2548. manually B$manually
  2549. mydomain $mydomain
  2550. myname    $myname
  2551. myorg    $myorg
  2552. uname    B$uname
  2553. ghname    B$ghname
  2554. v7mail    B$v7mail
  2555. newsrc    $newsrc
  2556. maxgroups $maxgroups
  2557. buflen    $buflen
  2558. lbuflen    $lbuflen
  2559. pathlen    $pathlen
  2560. datelen    $datelen
  2561. namelen    $namelen
  2562. fpathlen $fpathlen
  2563. termcap $termcap
  2564. !
  2565. !E!O!F!
  2566. chmod +x lib/setup
  2567.  
  2568. echo Part 3 of 7 extracted.
  2569.  
  2570.  
  2571.